<?php


namespace WenRuns\Laravel;


use WenRuns\Laravel\Link\Node;

class LinkList
{
    /**
     * @var null | Node
     */
    protected $head = null;

    /**
     * @var null | Node
     */
    protected $current = null;

    /**
     * @var null | Node
     */
    protected $end = null;

    /**
     * @param Node $node
     */
    public function append(Node $node)
    {
        if ($this->setHead($node)) {
            return $this;
        }
        $this->end->next($node);
        $this->current = $this->end = $node;
        return $this;
    }

    /**
     * @param Node $node
     * @return $this
     */
    public function shift(Node $node)
    {
        if ($this->setHead($node)) {
            return $this;
        }
        $this->head->prev($node);
        $this->current = $this->head = $node;
        return $this;
    }

    /**
     * @param Node $node
     * @param Node $new
     * @return $this
     */
    public function insertBefore(Node $node, Node $new)
    {
        if ($this->head == $node) {
            $this->head = $node;
        }
        if ($prev = $node->prev()) {
            $new->prev($prev);
        }
        $node->prev($new);
        $this->current = $new;
        return $this;
    }

    /**
     * @param Node $node
     * @param Node $new
     * @return $this
     */
    public function insertAfter(Node $node, Node $new)
    {
        if ($this->end == $node) {
            $this->end = $new;
        }
        if ($next = $node->next()) {
            $new->next($next);
        }
        $node->next($new);
        $this->current = $new;
        return $this;
    }

    /**
     * @param Node $node
     * @return $this
     */
    protected function setHead(Node $node)
    {
        if (empty($this->head)) {
            $this->head = $node;
            $this->end = $node;
            return true;
        }
        return false;
    }

    public function loop(\Closure $closure, $reverse = false)
    {
        if ($reverse) {
            $node = $this->end;
        } else {
            $node = $this->head;
        }
        do {
            $closure->call($this, $node);
        } while ($node = $node->next());
    }
}
